package com.ds.infrastructure.hyperspace.container.admin;

import com.ds.infrastructure.hyperspace.container.admin.processor.ApplyConfigProcessor;
import com.ds.infrastructure.hyperspace.container.internal.NettyContainer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @author  Weishaoying
 */
@Slf4j
public class ConsoleClientHandler extends SimpleChannelInboundHandler {

    private NettyContainer container;

    private ByteBuf responseByteBuf = null;

    private ApplyConfigProcessor applyConfigProcessor;

    public ConsoleClientHandler(NettyContainer container) {
        this.container = container;
        this.applyConfigProcessor = new ApplyConfigProcessor();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HttpResponse) {
            HttpResponse response = (HttpResponse) msg;
            Integer contentLength = response.headers().getInt(HttpHeaderNames.CONTENT_LENGTH);
            if (contentLength != null) {
                responseByteBuf = Unpooled.buffer(contentLength.intValue());
            } else {
                responseByteBuf = null;
            }
        }
        if (msg instanceof HttpContent) {
            HttpContent content = (HttpContent) msg;
            ByteBuf currentContent = content.content();
            if (currentContent.isReadable() && responseByteBuf != null) {
                responseByteBuf.writeBytes(currentContent);
            }
            if (content instanceof LastHttpContent) {
                try {
                    if (responseByteBuf != null) {
                        applyConfigProcessor.process(container, responseByteBuf.array());
                    }
                } finally {
                    ReferenceCountUtil.release(responseByteBuf);
                    ctx.close();
                }
            }
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("ConsoleClientHandler failed!", cause.getMessage());
        ctx.close();
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

}
